var child_process=require("child_process");
var fs=require("fs-extra");
var request=require("request");
var shell=require("shelljs");
var decompress=require("decompress");
var os=require("os");
var path=require("path");
var readline=require("readline");
var download=require("lei-download")
var argv=require("yargs").argv;
async function  install(p,run) {
    console.log("下载DOClever服务端...")
    await downloadAndUnzip("http://p6yjvhgo8.bkt.clouddn.com/server.zip",path.join(p,"server.zip"));
    console.log("安装依赖模块")
    shell.cd(p);
    await handleNpmInstall();
    console.log(`DOClever安装在目录${p}下`)
    if(run)
    {
        let execPath=path.join(p,"bin/www");
        child_process.execSync(`node ${execPath}`,{stdio: 'inherit'})
    }
}

function downloadFile(src,dest) {
    return new Promise(function (resolve,reject) {
        download(src, dest, function (size,total) {
            process.stdout.write (`进度：${ parseInt((size/total)*100) }%\r`);
        }, (err, filename) => {
            if (err) {
                console.log(`${ err }`);
                reject()
            }
            else {
                process.stdout.write("\n");
                console.log(`下载完成,开始解压`);
                resolve();
            }
        });
    })
}

async function installWithoutSetup(p) {
    console.log("下载DOClever服务端...")
    await downloadFile("http://p6yjvhgo8.bkt.clouddn.com/serverunpack.zip",path.join(p,"server.zip"));
    let option={};
    if(process.platform=="win32")
    {
        option.filter=function (file) {
            if(file.path.includes(".bin"))
            {
                return false;
            }
            else
            {
                return true;
            }
        }
    }
    await decompress(path.join(p,"server.zip"),p,option);
    await fs.remove(path.join(p,"server.zip"));
    console.log("解压完成")
    let execPath=path.join(p,"bin/www");
    child_process.execSync(`node ${execPath}`,{stdio: 'inherit'})
}

async function updateWithoutSetup(p) {
    console.log("更新DOClever服务端...")
    await downloadFile("http://p6yjvhgo8.bkt.clouddn.com/serverunpack.zip",path.join(p,"server.zip"));
    let option={};
    if(process.platform=="win32")
    {
        option.filter=function (file) {
            if(file.path.includes(".bin"))
            {
                return false;
            }
            else
            {
                return true;
            }
        }
    }
    await decompress(path.join(p,"server.zip"),p,option);
    await fs.remove(path.join(p,"server.zip"));
    console.log("解压完成")
}

function versionDiff(obj1,obj2) {
    var verArr=obj1.split(".");
    var verLocalArr=obj2.split(".");
    var bNew=false;
    for(var i=0;i<3;i++)
    {
        if(parseInt(verArr[i])>parseInt(verLocalArr[i]))
        {
            bNew=true;
            break;
        }
        else if(parseInt(verArr[i])<parseInt(verLocalArr[i]))
        {
            break;
        }
    }
    if(bNew)
    {
        return true;
    }
    else
    {
        return false;
    }
}

function downloadAndUnzip(url,dest) {
    return new Promise(function (resolve,reject) {
        let pipe=request(url).pipe(fs.createWriteStream(dest));
        pipe.on("finish",async function () {
            await decompress(dest,path.join(dest,".."));
            await fs.remove(dest);
            resolve();
        })
        pipe.on("error",async function (err) {
            reject(err.message);
        })
    })
}

function getUpdateVersion() {
    return new Promise(function (resolve,reject) {
        request("http://p6yjvhgo8.bkt.clouddn.com/ver.json",function (err,response,body) {
            let obj=JSON.parse(body);
            let version=obj.version;
            resolve(version);
        })
    })
}

function handleNpmInstall(){
    return new Promise(function(resolve, reject){
        let child = shell.exec('npm install -q --production --registry https://registry.npm.taobao.org', {async: true, silent: true});
        child.stdout.on('data', (data) => {
            console.log(` ${data}`);
        });
        child.stderr.on('data', (data) => {
            console.log(` ${data}`);
        });
        child.on('close', (code) => {
            resolve(true);
        });
    })
}

async function run() {
    try
    {
        let question=function (title) {
            let read=readline.createInterface({
                input: process.stdin,
                output: process.stdout
            });
            return new Promise(function (resolve,reject) {
                read.question(title,function (answer) {
                    read.close();
                    resolve(answer);
                })
            })
        }
        let nodeVersion = shell.exec('node -v', {silent: true}).substr(1);
        if(!nodeVersion.startsWith("8")){
            throw new Error('DOClever需要node 8的lts版本')
        }
        let p=os.homedir();
        let pPath=path.join(__dirname,"path");
        let first=false;
        let defaultPath=path.join(p,"DOClever-Server");
        if(!(await fs.exists(pPath)))
        {
            first=true;
            p=defaultPath;
        }
        else
        {
            p=(await fs.readFile(pPath)).toString();
        }
        if(argv.uninstall)
        {
            await fs.remove(path.join(__dirname,"path"));
            await fs.remove(p);
            console.log("删除完成");
        }
        else if(first)
        {
            let input=await question(`请输入你需要下载到的目录（请放到一个空目录里，默认目录：${defaultPath}）`);
            if(input)
            {
                p=input;
            }
            else
            {
                p=defaultPath;
            }
            await fs.writeFile(path.join(__dirname,"path"),p);
            if(!(await fs.exists(p)))
            {
                await fs.mkdir(p);
            }
            if(argv.installwithoutsetup)
            {
                installWithoutSetup(p);
            }
            else if(argv.uninstall || argv.rebuild || argv.stop || argv.restart || argv.silent || argv.update)
            {
                console.log("DOClever没有安装，请先安装");
            }
            else
            {
                install(p,1);
            }
        }
        else if(argv.rebuild)
        {
            await fs.remove(p);
            await fs.mkdir(p);
            install(p,1);
        }
        else if(argv.silent)
        {
            let configPath=path.join(p,"config.json");
            if(!(await fs.exists(configPath)))
            {
                console.log("请先直接运行doclever,完成服务端的配置")
                return;
            }
            let foreverPath=path.join(__dirname,"..","lib/forever/bin/forever");
            if(process.platform=="win32")
            {
                let binPath=path.join(p,"bin");
                process.chdir(binPath);
                child_process.exec(`node ${foreverPath} start www`,{stdio: 'inherit'})
            }
            else
            {
                let execPath=path.join(p,"bin/www");
                child_process.exec(`${foreverPath} start ${execPath}`,{stdio: 'inherit'})
            }
        }
        else if(argv.stop)
        {
            let foreverPath=path.join(__dirname,"..","lib/forever/bin/forever");
            if(process.platform=="win32")
            {
                let binPath=path.join(p,"bin");
                process.chdir(binPath);
                child_process.exec(`node ${foreverPath} stop www`,{stdio: 'inherit'})
            }
            else
            {
                let execPath=path.join(p,"bin/www");
                child_process.exec(`${foreverPath} stop ${execPath}`,{stdio: 'inherit'})
            }
        }
        else if(argv.restart)
        {
            let foreverPath=path.join(__dirname,"..","lib/forever/bin/forever");
            if(process.platform=="win32")
            {
                let binPath=path.join(p,"bin");
                process.chdir(binPath);
                child_process.exec(`node ${foreverPath} restart www`,{stdio: 'inherit'})
            }
            else
            {
                let execPath=path.join(p,"bin/www");
                child_process.exec(`${foreverPath} restart ${execPath}`,{stdio: 'inherit'})
            }
        }
        else if(argv.updatewithoutsetup)
        {
            let pVer=path.join(p,"ver.json");
            if(!(await fs.exists(pVer)))
            {
                console.log("请先运行doclever");
                return;
            }
            let verLocalContent=(await fs.readFile(pVer)).toString();
            let verLocal=JSON.parse(verLocalContent).version;
            let verUpdate=await getUpdateVersion();
            if(versionDiff(verUpdate,verLocal))
            {
                console.log(`发现新版本${verUpdate}`)
                let dirs=await fs.readdir(p);
                for(let o of dirs)
                {
                    if(o!="config.json")
                    {
                        await fs.remove(path.join(p,o));
                    }
                }
                await updateWithoutSetup(p);
                console.log(`新版本安装完成后，请启动doclever`)
            }
            else
            {
                console.log(`当前已经是最新版本`)
            }
        }
        else if(argv.update)
        {
            let pVer=path.join(p,"ver.json");
            if(!(await fs.exists(pVer)))
            {
                console.log("请先运行doclever");
                return;
            }
            let verLocalContent=(await fs.readFile(pVer)).toString();
            let verLocal=JSON.parse(verLocalContent).version;
            let verUpdate=await getUpdateVersion();
            if(versionDiff(verUpdate,verLocal))
            {
                console.log(`发现新版本${verUpdate}`)
                let dirs=await fs.readdir(p);
                for(let o of dirs)
                {
                    if(o!="config.json")
                    {
                        await fs.remove(path.join(p,o));
                    }
                }
                await install(p);
                console.log(`新版本安装完成后，请启动doclever`)
            }
            else
            {
                console.log(`当前已经是最新版本`)
            }
        }
        else if(argv.h)
        {
            console.log(`
                --silent  后台运行
                --stop   停止
                --update  升级服务端
                --rebuild  重新安装服务端
                --uninstall  卸载
                --restart  重启  
                --installwithoutsetup  直接下载绿色版本，不用npm intsall
                --updatewithoutsetup  直接更新绿色版本，不用npm intsall
            `)
        }
        else
        {
            let execPath=path.join(p,"bin/www");
            child_process.execSync(`node ${execPath}`,{stdio: 'inherit'})
        }
    }
    catch (err)
    {
        console.log(err.message);
    }

}

run();